package jadex.examples.hunterprey.creature.preys.Njftprey;

import jadex.examples.hunterprey.*;

import java.util.ArrayList;

public class NjftVision {
	/**
	 * An ArrayList that contains Objects extending the class CreatureData.
	 * List Elements are not Compared by using the elements equals() method, but by their AgendIdentifier's equals() method. (see jadex.adapter.fipa.AgentIdentifier)
	 * The reason is, that a CreatureData's equals() method is using the current Location to identify a Creature. By using the AID Creatures can be identified over time (and movement).  
	 * @author Niko
	 *
	 * @param <E> a class extending jadex.examples.hunterprey.CreatureData
	 */
	public class AgentList<E extends CreatureData> extends ArrayList<E>{
		private static final long serialVersionUID = 1L;

		/**
		 * Searches the ArrayList for the CreatureData object.
		 * the given object and the lists objects are compared by their AID's equals() method and not by their own equals method, because the CreatureDatas equals method uses the location for it's equals method.
		 * @param obj the object to look for
		 * @return true if creature is contained, false if not
		 */
		public boolean contains(E obj){
			for(int i=0;i<this.size();i++){
				if(this.get(i).getAID().equals(obj.getAID()))
					return true;
			}
			return false;
		}
		/**
		 * Replaces the object in the List, identified by it's AID.
		 * @param obj
		 * @return true if an object was replaced, false if object was not in the list. In this case the object was added at the end of the list instead.
		 */
		public boolean replace(E obj){
			int index = indexOf(obj);
			if(index <= 0)
				this.set(index,obj);
			else{
				this.add(obj);
				return false;
			}
			return true;
		}
		/**
		 * Gives the index of the given object.
		 * the given object and the lists objects are compared by their AID's equals() method and not by their own equals method, because the CreatureDatas equals method uses the location for it's equals method.
		 * @param obj the object to look for
		 * @return the last index of the object in the list, or -1 if it isn't contained.   
		 */
		public int indexOf(E obj){
			for(int i=this.size()-1;i>=0;i--){
				if(this.get(i).getAID().equals(obj.getAID()))
					return i;
			}
			return -1;
		}
	}
	private static NjftVision ref = new NjftVision();
	
	ArrayList<Obstacle> trees;
	AgentList<Hunter> hunter;
	ArrayList<Food> food;
	public static NjftVision getInstance(){
		return ref;
	}
	private NjftVision(){
		trees = new ArrayList<Obstacle>();
		hunter = new AgentList<Hunter>();
		food = new ArrayList<Food>();
		
	}
	
	void addVision(Vision vision){
		WorldObject[] objs = vision.getObjects();
		for(int i=0; i<objs.length;i++){
			//What an object do we have here?
			Class<? extends WorldObject> objClass = objs[i].getClass();
			if (objClass.isInstance(Obstacle.class) ){
				Obstacle obstac = (Obstacle)objs[i];
				if (!trees.contains(obstac))
					trees.add(obstac);
			}else if(objClass.isInstance(Food.class)){
				Food salad = (Food) objs[i];
				if(!food.contains(salad))
					food.add(salad);
				
			}else if(objClass.isInstance(Hunter.class)){ // it _is_ my intention to use else-if as last branch. i don't want to get other types, if there are any...
				Hunter wolf = (Hunter) objs[i];
				hunter.replace(wolf);
				
			}
		}
	}
	//TODO make up something clever about the moving hunters   ~niko

}
